<?php

/**
 * Albireo Kernel
 *
 * @copyright  Copyright (c) 2010 Albireo Solutions
 * @package    Kernel
 */

use Nette\Object;
use Nette\Security\AuthenticationException;
use Nette\Security\Identity;
use Nette\Security\IAuthenticator;

use Celebrio\PasswordHasher;


/**
 * Users authenticator.
 *
 * @author     Albireo Solutions
 * @package    Kernel
 */
class KernelAuthenticator extends Object implements IAuthenticator {
    /**
     * Performs an authentication
     * @param  array $credentials sign in credentials
     * @return IIdentity
     * @throws AuthenticationException
     */
    public function authenticate(array $credentials) {
        $username = $credentials[self::USERNAME];
        $password = PasswordHasher::userHash($username, $credentials[self::PASSWORD]);
        $row = dibi::fetch('SELECT [id], [first_name], [last_name], [password], [email], [language], [time_zone]
                    FROM [users] u JOIN [passwords] p ON ([id] = [user_id]) WHERE u.user_name=%s
                    AND p.created = (SELECT MAX([created]) FROM [passwords] WHERE [user_id] = [id])', $username);
        //TODO: je to takhle dobre? melo by byt, vyzkouset

        $rolesRows = dibi::fetchAll('SELECT [name] FROM [roles] JOIN [users_roles] ON ([role_id] = [id]) WHERE [user_id]=%i', $row['id']);


        /*
         * TODO: User with at least 1 non-guest role does not obtain the guest role
                 do we want the behaviour like this?
         */
        if (empty($rolesRows)) {
            $roles[] = "guest";
        } else {
            foreach ($rolesRows as $roleRow) {
                $roles[] = $roleRow->name;
            }
        }

        if (!$row) {
            throw new AuthenticationException(_("Invalid credentials."), self::IDENTITY_NOT_FOUND);
        }
        if ($row->password !== $password) {
            throw new AuthenticationException(_("Invalid credentials."), self::INVALID_CREDENTIAL);
        }
        //TODO: keep password hash with salt and pepper in user's session

        return new Identity($username, $roles, $row);
    }
}